// 
// $Id$
//
// Definition of USB_Device class
//
// <Nitin Karkhanis> <<nkarkhan@yahoo.com>>
// Created on: <31-Jan-2007 14:58:24 nitin_karkhanis>
//
// Copyright (C) <Nitin Karkhanis>.  All rights reserved.
//

#ifndef FTDI_Device_HPP
#define FTDI_Device_HPP

#include <errno.h>
#include <string.h>
#include <windows.h>
#include <FTD2XX.h>
#include <inttypes.h>
//using namespace std;

/*! \file FTDI_Device.hpp
  Definition of FTDI_Device class
*/
class FTDI_Device
{
#define CBUS_BIG_BANG_MODE 0x20
#define PIN_INPUT          0
#define PIN_OUTPUT         1
#define MAX_IO_PINS        4
private:
    FT_HANDLE   ft_handle;
    uint8_t     pin_mode;
    uint8_t     write_val;
    uint8_t     read_val;
    bool        found;
private:
    int init_device(void);
    int pin_mode_get(uint8_t pin_num, uint8_t *mode);
    int device_mode_val_write(void);
    int device_mode_val_read(void);
    
protected:

public:
    typedef enum {
        INPUT,
        OUTPUT } io_type;

    FTDI_Device();                 /*< attaches itself to the first FTDI device found */
    FTDI_Device(long LocationID);  /*< Assumes multiple devices */
    ~FTDI_Device();
    bool device_present(void);
    int pin_set(uint8_t pin_num, io_type io); /*< pin Numbers start at 0 */
    int pin_write(uint8_t pin_num, bool );       /*< pin numbers start at 0, true for high */
    int pin_read(uint8_t pin_num, bool *);       /*< pin numbers start at 0, true for high */
};

/*******************************************************************************
 * Bit Manipulation routines
 ******************************************************************************/

static inline
int set_bit_8 (uint8_t *old_val, uint8_t bit_num, bool bit_val)
{
    uint8_t scratch_val;

    if (bit_num > 7) {
//        cout << __FUNCTION__ << ":Called with " << bit_num << endl; 
        return -1;
    }
    scratch_val = 0x1 << bit_num;         // Move '1' to the right place
    *old_val = (*old_val) | scratch_val;  // Get position bit_num to say '1'
    if (bit_val) {                        // if this was supposed to be '1' then we are done
        // We are already done
    } else {                              // if this was supposed to be '0' then xor it again 
        *old_val = (*old_val) ^ scratch_val;
    }
    return 0;
}

static inline
int get_bit_8(uint8_t val, uint8_t bit_num, bool *bit_val)
{
    if (bit_num > 7) {
//        cout << __FUNCTION__ << ":Called with " << bit_num << endl; 
        return -1;
    }
    val = val >> bit_num;
    val = val & 0x1;
    *bit_val = val ? true : false;
    return 0;
}

#endif // FTDI_Device_HPP
